package com.tencent.wxcloudrun.util;


import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;


import com.baomidou.mybatisplus.core.toolkit.StringUtils;

import com.tencent.wxcloudrun.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public final class DateUtils {
    public static final String formatTimeStr = "yyyy-MM-dd HH:mm:ss";
    public static final String formatDateStr = "yyyy-MM-dd";

    public static final DateTimeFormatter LOCAL_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(formatTimeStr);
    public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    public static final String PATTERN_YYYYMMDD = "yyyyMMdd";

    public static final String PATTERN_YYYY_MM_DD = "yyyy-MM-dd";

    public static final String PATTERN_HHMMSS = "HHmmss";

    public static final String PATTERN_HH_MM_SS = "HH:mm:ss";

    public static final String PATTERN_HH_MM_SS_SSS = "HH:mm:ss.SSS";
    public static final DateTimeFormatter FORMATTER_YYYYMMDD = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDD);

    private DateUtils() {}

    /**
     * method description: 取指定时间的前N分钟
     *
     * @param nowTime
     * @param minutes
     * @return java.lang.Integer
     * @author Ryan Zhao
     * @date 2023-09-13 15:12
     */
    public static Integer getBeforeOfBegnTime(Integer nowTime, int minutes) {
        String actiBegnTimeStr = DateUtils.suppleTime(String.valueOf(nowTime));
        LocalTime time = LocalTime.parse(actiBegnTimeStr, DateTimeFormatter.ofPattern("HHmmss"));
        LocalTime beforeTime = time.minusMinutes(minutes);
        String beforeTimeStr = beforeTime.format(DateTimeFormatter.ofPattern("HHmmss"));
        return Integer.valueOf(beforeTimeStr);
    }

    /**
     * method description: 取指定时间的后N分钟
     *
     * @param nowTime
     * @param minutes
     * @return java.lang.Integer
     * @author Ryan Zhao
     * @date 2023-09-13 14:43
     */
    public static Integer getAfterOfTimeByMinutes(Integer nowTime, int minutes) {
        String nowTimeStr = DateUtils.suppleTime(String.valueOf(nowTime));
        LocalTime time = LocalTime.parse(nowTimeStr, DateTimeFormatter.ofPattern("HHmmss"));
        LocalTime afterTime = time.plusMinutes(minutes);
        String afterTimeStr = afterTime.format(DateTimeFormatter.ofPattern("HHmmss"));
        return Integer.valueOf(afterTimeStr);
    }

    /**
     * method description: 取指定时间的后N分钟
     *
     * @param nowTime
     * @param seconds
     * @return java.lang.Integer
     * @author Ryan Zhao
     * @date 2023-09-13 14:43
     */
    public static Integer getAfterOfTimeBySeconds(Integer nowTime, int seconds) {
        String nowTimeStr = DateUtils.suppleTime(String.valueOf(nowTime));
        LocalTime time = LocalTime.parse(nowTimeStr, DateTimeFormatter.ofPattern("HHmmss"));
        LocalTime afterTime = time.plusSeconds(seconds);
        String afterTimeStr = afterTime.format(DateTimeFormatter.ofPattern("HHmmss"));
        return Integer.valueOf(afterTimeStr);
    }

    /**
     * method description: 整形日期转Date
     *
     * @param date yyyyMMdd
     * @return java.util.Date
     * @author Kelvin
     * @date 2022/12/7 21:50
     */
    public static Date intToDate(Integer date) {
        return stringToDate(date.toString());
    }

    /**
     * method description: 字符串日期转Date
     *
     * @param date yyyyMMdd
     * @return java.util.Date
     * @author Kelvin
     * @date 2022/12/7 21:50
     */
    public static Date stringToDate(String date) {
        LocalDate parse = LocalDate.parse(date, FORMATTER_YYYYMMDD);
        return Date.from(parse.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * method description: 字符串日期转Date
     *
     * @param date yyyyMMdd
     * @param pattern 日期格式
     * @return java.util.Date
     * @author Kelvin
     * @date 2022/12/7 21:50
     */
    public static Date stringToDate(String date, String pattern) {
        LocalDate parse = LocalDate.parse(date, DateTimeFormatter.ofPattern(pattern));
        return Date.from(parse.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * method description: Date转整形日期
     *
     * @param date 日期
     * @return java.lang.Integer
     * @author Kelvin
     * @date 2022/12/7 21:50
     */
    public static Integer dateToInt(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(PATTERN_YYYYMMDD);
        return Integer.parseInt(sdf.format(date));
    }

    /**
     * method description: Date转字符串日期
     *
     * @param date 日期
     * @return java.lang.String 格式为yyyyMMdd
     * @author Kelvin
     * @date 2022/12/7 21:50
     */
    public static String dateToString(Date date) {
        return dateToString(date, PATTERN_YYYYMMDD);
    }

    /**
     * method description: Date转字符串日期
     *
     * @param date 日期
     * @param pattern 日期格式
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/7 21:50
     */
    public static String dateToString(Date date, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }

    /**
     * method description: 日期格式转换
     *
     * @param date 日期 格式必须为yyyyMMdd
     * @param pattern 日期格式
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/7 21:50
     */
    public static String dateToString(String date, String pattern) {
        return dateToString(date, PATTERN_YYYYMMDD, pattern);
    }

    /**
     * method description: 日期格式转换
     *
     * @param date 日期
     * @param fromPattern 日期格式
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/7 21:50
     */
    public static String dateToString(String date, String fromPattern, String toPattern) {
        SimpleDateFormat sdf1 = new SimpleDateFormat(fromPattern);
        SimpleDateFormat sdf2 = new SimpleDateFormat(toPattern);
        return sdf2.format(parse(date, sdf1));
    }

    /**
     * method description: Date转字符日期yyyy-MM-dd
     *
     * @param date 日期
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:41
     */
    public static String dateToStringShow(Date date) {
        return dateToString(date, PATTERN_YYYY_MM_DD);
    }

    /**
     * method description: yyyyMMdd转字符日期yyyy-MM-dd
     *
     * @param date 日期 格式必须为yyyyMMdd
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:41
     */
    public static String dateToStringShow(String date) {
        return dateToString(date, PATTERN_YYYY_MM_DD);
    }

    /**
     * method description: yyyyMMdd转字符日期yyyy-MM-dd
     *
     * @param date 日期 格式必须为yyyyMMdd
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:41
     */
    public static String dateToStringShow(Integer date) {
        return dateToString(date.toString(), PATTERN_YYYY_MM_DD);
    }

    /**
     * method description: Date转整形时间
     *
     * @param time 时间 格式必须为HHmmss
     * @return java.lang.Integer
     * @author Kelvin
     * @date 2022/12/8 10:01
     */
    public static Integer timeToInt(Date time) {
        return Integer.parseInt(timeToString(time));
    }

    /**
     * method description: Date转整形时间
     *
     * @param time 时间 格式必须为HHmmss
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:01
     */
    public static String timeToString(Date time) {
        return timeToString(time, PATTERN_HHMMSS);
    }

    /**
     * method description: Date转整形时间
     *
     * @param time 时间
     * @param pattern 时间格式
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:01
     */
    public static String timeToString(Date time, String pattern) {
        SimpleDateFormat sdf1 = new SimpleDateFormat(pattern);
        return sdf1.format(time);
    }

    /**
     * method description: 时间格式转换
     *
     * @param time 时间 格式必须为HHmmss
     * @param pattern 时间格式
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:01
     */
    public static String timeToString(String time, String pattern) {
        return timeToString(time, PATTERN_HHMMSS, pattern);
    }

    public static String intTimeToString(String time, String pattern) {
        return timeToString(suppleTime(time), PATTERN_HHMMSS, pattern);
    }

    /**
     * 时间补0到6为数字
     *
     * @param time 时间
     * @return 6位时间
     */
    public static String suppleTime(String time) {
        StringBuilder fullTime = new StringBuilder(time);
        while (fullTime.length() < 6) {
            fullTime.insert(0, "0");
        }
        return fullTime.toString();
    }

    /**
     * method description: 时间格式转换
     *
     * @param time 时间
     * @param fromPattern 来源时间格式
     * @param toPattern 目标时间格式
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:01
     */
    public static String timeToString(String time, String fromPattern, String toPattern) {
        SimpleDateFormat sdf1 = new SimpleDateFormat(fromPattern);
        SimpleDateFormat sdf2 = new SimpleDateFormat(toPattern);
        return sdf2.format(parse(time, sdf1));
    }

    /**
     * method description: Date转字符时间HH:mm:ss
     *
     * @param time 时间
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:38
     */
    public static String timeToStringShow(Date time) {
        return timeToString(time, PATTERN_HH_MM_SS);
    }

    /**
     * method description: HHmmss转字符时间HH:mm:ss
     *
     * @param time 时间 格式必须为HHmmss
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:38
     */
    public static String timeToStringShow(String time) {
        return timeToString(time, PATTERN_HH_MM_SS);
    }

    /**
     * method description: HHmmss转字符时间HH:mm:ss
     *
     * @param time 时间 格式必须为HHmmss
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:38
     */
    public static String timeToStringShow(Integer time) {
        return timeToString(time.toString(), PATTERN_HH_MM_SS);
    }

    /**
     * method description: 获取当前整形日期
     *
     * @return java.lang.Integer
     * @author Kelvin
     * @date 2022/12/8 10:17
     */
    public static Integer nowIntDate() {
        return dateToInt(new Date());
    }

    /**
     * method description: 获取当前字符串日期
     *
     * @return java.lang.String 格式yyyyMMss
     * @author Kelvin
     * @date 2022/12/8 10:17
     */
    public static String nowStringDate() {
        return dateToString(new Date());
    }

    /**
     * method description: 获取当前字符串日期
     *
     * @param pattern 日期格式
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:17
     */
    public static String nowStringDate(String pattern) {
        return dateToString(new Date(), pattern);
    }

    /**
     * method description: 获取当前字符串日期
     *
     * @return java.lang.String 格式yyyy:MM:ss
     * @author Kelvin
     * @date 2022/12/8 10:17
     */
    public static String nowStringDateShow() {
        return nowStringDate(PATTERN_YYYY_MM_DD);
    }

    /**
     * method description: 获取当前整形日期
     *
     * @return java.lang.Integer
     * @author Kelvin
     * @date 2022/12/8 13:45
     */
    public static Integer nowIntTime() {
        return Integer.parseInt(nowStringTime());
    }

    /**
     * method description: 获取当前字符串时间
     *
     * @return java.lang.String 格式为HHmmss
     * @author Kelvin
     * @date 2022/12/8 10:17
     */
    public static String nowStringTime() {
        return nowStringTime(PATTERN_HHMMSS);
    }

    /**
     * method description: 获取当前字符串时间
     *
     * @param pattern 时间格式
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:17
     */
    public static String nowStringTime(String pattern) {
        return timeToString(new Date(), pattern);
    }

    /**
     * method description: 获取当前字符串时间
     *
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:17
     */
    public static String nowStringTimeShow() {
        return nowStringTime(PATTERN_HH_MM_SS);
    }

    /**
     * method description: 获取当前字符串时间 HH:mm:ss.SSS
     *
     * @return java.lang.String
     * @author Kelvin
     * @date 2022/12/8 10:17
     */
    public static String nowStringTimeMillsShow() {
        return nowStringTime(PATTERN_HH_MM_SS_SSS);
    }

    /**
     * method description: 根据格式解析字符串日期
     *
     * @param date 日期
     * @param sdf 格式化
     * @return java.util.Date
     * @author Kelvin
     * @date 2022/12/8 14:20
     */
    private static Date parse(String date, SimpleDateFormat sdf) {
        try {
            return sdf.parse(date);
        } catch (ParseException e) {
            log.error("日期解析异常", e);
            throw new BusinessException("日期解析异常");
        }
    }

    @Deprecated
    public static Date toDate(String value) {
        return toDate(value, "yyyy-MM-dd");
    }

    @Deprecated
    public static Date toDate(String value, String format) {
        if (StringUtils.isBlank(value)) {
            return null;
        }
        DateFormat dateFormat = new SimpleDateFormat(format);
        try {
            return dateFormat.parse(value);
        } catch (ParseException e) {
            return null;
        }
    }

    @Deprecated
    public static String stringNow() {
        return stringNow("yyyy-MM-dd");
    }

    @Deprecated
    public static String stringNow(String pattern) {
        return LocalDate.now().format(DateTimeFormatter.ofPattern(pattern));
    }

    @Deprecated
    public static int intNow() {
        return Integer.parseInt(stringNow("yyyyMMdd"));
    }

    @Deprecated
    public static Long intThisDateTime() {
        String pattern = "yyyyMMddHHmmss";
        return Long.parseLong(LocalDateTime.now().format(DateTimeFormatter.ofPattern(pattern)));
    }

    @Deprecated
    public static String intDateTime() {
        String pattern = "yyyyMMddHHmmss";
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * @description: String类型 yyyy-MM-dd HH:mm:ss 转换 Logn类型 yyyyMMddHHmmss
     * @author solomon
     * @date 2022/6/28 13:38
     */
    @Deprecated
    public static Long parseStringToDateTime(String dataTime) {
        Date date;
        try {
            date = parseDate((dataTime), "yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
            return Long.parseLong(format.format(date));
        } catch (ParseException e) {
            log.info("");
        }
        return intThisDateTime();

    }

    @Deprecated
    public static String intDate(Date date) {
        String pattern = "yyyyMMdd";
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        return format.format(date);
    }

    /**
     * 将日期格式化成整数yyyyMMddHHmmss
     *
     * @param date 日期
     * @return yyyyMMddHHmmss
     */
    @Deprecated
    public static Long longDateTime(Date date) {
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        String format = DATE_TIME_FORMATTER.format(localDateTime);
        return Long.parseLong(format);
    }

    @Deprecated
    public static Integer intNowTime() {
        String pattern = "HHmmss";
        return Integer.parseInt(LocalTime.now().format(DateTimeFormatter.ofPattern(pattern)));
    }

    @Deprecated
    public static String nowTime(boolean mills) {
        String pattern = mills ? "HH:mm:ss.SSS" : "HH:mm:ss";
        return LocalTime.now().format(DateTimeFormatter.ofPattern(pattern));
    }

    @Deprecated
    public static String nowDateTime() {
        return nowDateTime(false);
    }

    @Deprecated
    public static String nowDateTime(boolean mills) {
        String pattern = mills ? "yyyy-MM-dd HH:mm:ss.SSS" : "yyyy-MM-dd HH:mm:ss";
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(pattern));
    }

    @Deprecated
    public static String nowNumberDateTime(boolean mills) {
        String pattern = mills ? "yyyyMMddHHmmssSSS" : "yyyyMMddHHmmss";
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(pattern));
    }

    public static String getMonthDateHourMin() {
        return nowNumberDateTime(false).substring(4, 12);
    }

    @Deprecated
    public static Date parseDate(int date) throws ParseException {
        return parseDate(String.valueOf(date), "yyyyMMdd");
    }

    @Deprecated
    public static Date parseDate(String date) throws ParseException {
        return parseDate(date, "yyyy-MM-dd");
    }

    public static Date parseDate(String date, String pattern) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        return dateFormat.parse(date);
    }

    @Deprecated
    public static Date parseDateTime(String date) {
        try {
            return parseDate(date, formatTimeStr);
        } catch (ParseException e) {
            log.info("解析String类型时间格式为 yyyy-MM-dd HH:mm:ss 解析错误：{}", date);
        }
        return null;
    }

    @Deprecated
    public static String parseStringDate(int date) {
        Date dateTime = null;
        try {
            dateTime = parseDate(date);
            return getTimeToString(dateTime);
        } catch (ParseException e) {
            log.info("转换时间错误 :{}", e.getMessage());
        }
        return null;
    }

    @Deprecated
    public static String getTimeStringToOtherString(String date, String pattern0, String pattern1) throws ParseException {
        Date date0 = parseDate(date, pattern0);
        SimpleDateFormat sdf1 = new SimpleDateFormat(pattern1);
        return sdf1.format(date0);
    }

    @Deprecated
    public static String getTimeToString(Date time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(time);
    }

    /**
     * 计算两个日期之间相差的天数
     *
     * @param smdate 较小的时间
     * @param bdate 较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int daysBetween(Date smdate, Date bdate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            smdate = sdf.parse(sdf.format(smdate));
            bdate = sdf.parse(sdf.format(bdate));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar cal = Calendar.getInstance();

        cal.setTime(smdate);

        long time1 = cal.getTimeInMillis();

        cal.setTime(bdate);

        long time2 = cal.getTimeInMillis();

        long betweenDays = (time2 - time1) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(betweenDays));
    }

    /**
     * 计算当前日期的days天数后的日期
     *
     * @param days 天数
     * @throws ParseException
     */
    public static String daysAfter(String currentDate, int days) {
        return doCalculateAfter(currentDate, days, 1);
    }

    /**
     * 计算当前日期的months月后的日期
     *
     * @param months 月数
     * @throws ParseException
     */
    public static String monthsAfter(String currentDate, int months) {
        return doCalculateAfter(currentDate, months, 2);
    }

    private static String doCalculateAfter(String currentDate, int item, int type) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Calendar curr = Calendar.getInstance();
        try {
            curr.setTime(sdf.parse(currentDate));
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (type == 1) {
            curr.add(Calendar.DATE, item);
        } else {
            curr.add(Calendar.MONTH, item);
        }
        Date date = curr.getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
        return formatter.format(date);
    }

    /**
     * 获取传入日期的上一年的第一天
     *
     * @param date
     * @return
     */
    public static int getLastYearFirstDay(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        Calendar curr = Calendar.getInstance();
        try {
            curr.setTime(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        curr.add(Calendar.YEAR, -1);
        Date lastYearFirstDayDate = curr.getTime();

        return Integer.parseInt(sdf.format(lastYearFirstDayDate) + "0101");
    }

    public static int getThisYearFirstDay() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        return Integer.parseInt(sdf.format(new Date()) + "0101");
    }

    @Deprecated
    public static String formatDate(Date date) {
        return formatDate(date, "yyyy-MM-dd");
    }

    @Deprecated
    public static String formatDate(Date date, String format) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.format(date);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Deprecated
    public static String formatDate(LocalDateTime date) {
        return formatDate(date, "yyyy-MM-dd");
    }

    @Deprecated
    public static String formatDate(LocalDateTime date, String format) {
        try {
            DateTimeFormatter sdf = DateTimeFormatter.ofPattern(format);
            return sdf.format(date);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Date转换String类型
     *
     * @param date 时间value
     * @param format 时间转换格式
     * @return Date
     */
    @Deprecated
    public static String dateFormatString(Date date, String format) {
        SimpleDateFormat sf = new SimpleDateFormat(format);
        return sf.format(date);
    }
}
